(function () {
  window.layerManager = window.layerManager || new Map();

  class BaseLayer {
    constructor(options = {}) {
      this.minZoom = options.minZoom || 5;
      this.maxZoom = options.maxZoom || 21;
      // 图层名称 全局唯一
      this.name = options.name || '';
      // 点位大小
      this.iconSize = options.iconSize || 1;
      this.visible = options.visible || true; // 图层是否可见
      this.cacheData = options.cacheData || [];
      this.imgList = options.imgList || []; // 图层图片列表
    }

    // 初始化图层 默认创建点位图层
    initLayer(opts = {}) {
      // 创建图层数据源
      var sourceConfig = {
        type: 'geojson',
        data: {
          type: "FeatureCollection",
          features: []
        }
      }
      map.addSource(this.name, sourceConfig)

      this.layerSource = map.getSource(this.name)

      var layerConfig = {
        id: this.name,
        type: 'symbol',
        source: this.name,
        layout: {
          // 为图层设置引用的图片ID
          "icon-image": ['get', 'icon'],
          "icon-size": this.iconSize || 1,
        }
      }

      if (Object.keys(opts).length) {
        layerConfig = Object.assign({}, layerConfig, opts)
      }

      map.addLayer(layerConfig)

      this.layer = map.getLayer(this.name)

      window.layerManager.set(this.name, this)

      // 设置图层可见性
      this.setZoom()

      this.loadData()
    }

    /**
     *
     * 给一个feature
     * @param f
     * @param blinkConfig 闪烁配置
     * blinkConfig = {
     *   blinkEnd: Number, 闪烁次数 默认 10
     *   blinkSpeed: Number, 毫秒 闪烁速度 默认 500ms 建议最小300 ms
     *   blinkColor: String, 闪烁颜色 默认 red
     *
     * }
     */
    blinkLineFeatrue(f, blinkConfig) {
      // 创建立即停止控制
      window._blinkEndAni = false
      // 创建基础闪烁配置
      let config = Object.assign({}, {
        blinkEnd: 10,
        blinkSpeed: 500,
        blinkColor: 'yellow'
      }, blinkConfig || {})
      // 构造图层与数据源名称
      let name = '_temp_' + this.name
      if (map.getLayer(name) && map.getSource(name)) {
        map.removeLayer(name)
        map.removeSource(name)
        window._clear_ani_timeout && clearTimeout(window._clear_ani_timeout)
      }
      // 构建数据源
      var sourceConfig = {
        type: 'geojson',
        data: {
          type: "FeatureCollection",
          features: [f]
        }
      }
      map.addSource(name, sourceConfig)
      map.addLayer({
        id: name,
        type: 'line',
        source: name,
        layout: {
          'line-join': 'round',
          'line-cap': 'round'
        },
        paint: {
          'line-color': 'green',
          'line-width': f.properties.lineWidth || 5
        }
      })
      map.moveLayer(this.name, name)

      let index = 0
      let endIndex =  config.blinkEnd

      let startAni = () => {
        if (window._blinkEndAni || (index >= endIndex)) {
          map.removeLayer(name)
          map.removeSource(name)
          clearTimeout(window._clear_ani_timeout)
          return
        }

        window._clear_ani_timeout = setTimeout(() => {
          index += 1
          let bool = map.getLayer(name) && map.getSource(name)
          if (!bool) return
          if (index % 2 == 0) {
            map.setPaintProperty(name, 'line-opacity', 0);
          } else {
            map.setPaintProperty(name, 'line-color', config.blinkColor);
            map.setPaintProperty(name, 'line-opacity', 1);
            map.setPaintProperty(name, 'line-blur', .5);
          }
          startAni()
        }, config.blinkSpeed)
      }
      setTimeout(() => {
        startAni()
      }, 500)

      return {
        stop() {
          window._blinkEndAni = true
        }
      }
    }

    loadImage() {
      if (this.imgList.length) {
        this.imgList.forEach(item => {
          map.loadImage(item.value, (error, image) => {
            if (error) throw error;
            map.addImage(item.name, image);
          })
        })
      }
    }

    loadData() {}


    makeFeature(item) {

    }

    setTipHtml() {
      return ''
    }
    showTip(config={}) {
      if (window.popup) {
        window.popup.remove()
        window.popup = null
      }
      window.popup = new mapboxgl.Popup({ closeOnClick: false })
        .setLngLat(config.position)
        .setHTML(this.setTipHtml(config.feature, config.data))
        .addTo(map);
    }

    /**
     *
     * @param feature 当前定位元素
     * @param config 定位的配置
     */
    waveLocation(feature, config = {}) {
        let html = `
          <div class="container">
            <div class="ripple"></div>
            <div class="ripple"></div>
            <div class="ripple"></div>
        </div>
        `
      if (feature.geometry.type !== 'Point') return
      let position = feature.geometry.coordinates

      window.wave_popup = new mapboxgl.Popup({ closeOnClick: false })
        .setLngLat(position)
        .setHTML(html)
        .addTo(map);
      window.wave_popup.setOffset([-1, 25])
      let duration = 3000
      // 持续时间
      if (config.duration) {
        duration = config.duration
      }
      if (config.fly) {
        let bbox = turf.bbox(feature)
        map.fitBounds(bbox, {
          padding: 50
        })

      }
      setTimeout(_ => {
        window.wave_popup.remove()
      }, duration)
    }

    fitExend() {
      if (!this.layer || !this.layerSource) return
      let bbox = turf.bbox(this.layerSource._data)
      map.fitBounds(bbox)
    }

    refreshLayer() {
      var fs = []
      if (this.cacheData.length) {
        this.cacheData.forEach(item => {
          var feature = this.makeFeature(item)
          fs.push(feature)
        })
        let geoJson = {
          type: 'FeatureCollection',
          features: fs
        }
        this.layerSource.setData(geoJson)
      } else {
        this.layerSource.setData({
          type: 'FeatureCollection',
          features: []
        })
      }
    }

    setZoom(minZoom, maxZoom) {
      if (this.layer) {
        map.setLayerZoomRange(this.name, this.minZoom, this.maxZoom);
      }
    }

    // 设置图层可见性
    setVisible(visible) {
      this.visible = visible;
      if (this.layer) {
        if (visible) {
          map.setLayoutProperty(this.name, 'visibility', 'visible');
        } else {
          map.setLayoutProperty(this.name, 'visibility', 'none');
        }
      }
    }
  }

  window.BaseLayer = BaseLayer
})();
